package com.wawi.utils.gen;

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import com.wawi.utils.DateUtil;
import com.wawi.utils.StringUtil;

public class GenEntityUtil {
	
	protected String[] removedTableNamePrefixes = null;
	protected String[] removedTableName = null;
	protected String[] tableNames = null;
	protected String baseModelPackageName=null;
	protected String baseDaoPackageName=null;
    private Connection conn=null;

    
    public GenEntityUtil(){
    	this.conn=DBUtils.getConnection();
    	this.tableNames=DBUtils.getTableNames(conn);
    }
	public static GenEntityUtil me(){
		return new GenEntityUtil();
	}
    /**
     * 自动生成代码
     */
	public  void generate(){
		PreparedStatement ps=null;
		ResultSet rs=null;
		try {
			for(int i=0;i<tableNames.length;i++){
				if(!isRemoveTable(tableNames[i])){
					String sql="select * from "+tableNames[i];
					ps = conn.prepareStatement(sql);
					rs = ps.executeQuery();
					ResultSetMetaData rsmd = rs.getMetaData();
					int size = rsmd.getColumnCount();
					String[] colnames = new String[size];
					String[] colTypes = new String[size];
					for (int j = 0; j < size; j++) {
						colnames[j] = rsmd.getColumnName(j + 1);
						colTypes[j] = rsmd.getColumnTypeName(j + 1);
					}
					String entity = parse(colnames,colTypes,tableNames[i]);
					String dao = parseDao(tableNames[i]);
					generateFile(tableNames[i],entity,dao);
				}
			}
		} catch (Exception e) {
          e.printStackTrace();
		}finally{
			DBUtils.close(rs, ps, conn);
		}
	}
	/**
	 * 是否不自动生成代码的表
	 */
	public boolean isRemoveTable(String tablename){
		boolean flag=false;
		for(String str: removedTableName){
			if(str!=null&&!str.equals("")&&StringUtil.containsIgnoreCase(tablename, str)){
				flag=true;
			}
		}
		return flag;
	}
	/**
	 * 获取实体名称
	 */
	public String getRealTableName(String tablename){
		String str=tablename;
		for(String s: removedTableNamePrefixes){
			str=str.replaceAll(s, "");
		}
		str=StringUtil.underlineToCamelhump(str);
		str=StringUtil.firstCharToUpperCase(str);
		return str;
	}
	/**
	 * 获取属性名称
	 */
	public String getColumnName(String column){
		String str=column;
		if(column.contains("_")){
			str=str.toLowerCase();
			str=StringUtil.underlineToCamelhump(str);
		}else if(StringUtil.isAllUpperCase(str)){
			str=str.toLowerCase();
		}
		return str;
	}
	/*
	 * 自动生成entity,dao,controller,mybatis文件
	 */
	public void generateFile(String tablename,String entity,String dao){
		try {
			File directory = new File(".");
			String entityPath=directory.getCanonicalPath()+"\\src\\"+this.baseModelPackageName.replace(".", "\\")+"\\";
			entityPath=entityPath.replace("\\", "/");
			String daoPath=directory.getCanonicalPath()+"\\src\\"+this.baseDaoPackageName.replace(".", "\\")+"\\";
			daoPath=daoPath.replace("\\", "/");
			createFile(entityPath,getRealTableName(tablename)+".java",entity);
			//createFile(daoPath,getRealTableName(tablename)+"Dao.java",dao);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	/*
	 * 生成entity,dao文件
	 */
	public void createFile(String path,String filename,String content){
		try {
			File f=new File(path,filename);
			File file=new File(path);
			if(!file.exists()){
				file.mkdirs();
			}
			if(!f.exists()){
				f.createNewFile();
				FileWriter fw = new FileWriter(f);
				PrintWriter pw = new PrintWriter(fw);
				pw.println(content);
				pw.flush();
				pw.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 功能：生成实体类主体代码
	 */
	private String parse(String[] colnames, String[] colTypes,String tablename) {
		StringBuffer sb = new StringBuffer();
		
		sb.append("package " + this.baseModelPackageName + ";\r\n");
		sb.append("\r\n");
		//注释部分
		sb.append("/**\r\n");
		sb.append("* "+tablename+" 实体类\r\n");
		sb.append("* "+DateUtil.getDate()+" "+this.baseModelPackageName+"\r\n");
		sb.append("*/ \r\n");
		//实体部分
		sb.append("public class " + getRealTableName(tablename) + "{\r\n");
		processAllAttrs(sb,colnames,colTypes);//属性
		processAllMethod(sb,colnames,colTypes);//get set方法
		sb.append("}\r\n");
		return sb.toString();
	}
	/**
	 * 功能：生成Dao类主体代码
	 */
	public String parseDao(String tablename) {
		StringBuffer sb = new StringBuffer();
		
		sb.append("package " + this.baseDaoPackageName + ";\r\n");
		sb.append("\r\n");

		//实体部分
		sb.append("import cn.wawi.common.annotation.MybatisRepository;\r\n");
		sb.append("import cn.wawi.dao.BaseDao;\r\n");
		sb.append("import "+this.baseModelPackageName+"."+getRealTableName(tablename)+";\r\n");
		sb.append("@MybatisRepository\r\n");
		sb.append("public interface " + getRealTableName(tablename)+"Dao"+"<T extends "+getRealTableName(tablename)+">"+" extends BaseDao<T>" + " {\r\n");
		sb.append("}\r\n");
		return sb.toString();
	}

	/**
	 * 功能：生成所有方法
	 * @param sb
	 */
	private void processAllMethod(StringBuffer sb,String[] colnames,String[] colTypes) {
		for (int i = 0; i < colnames.length; i++) {
			String column=getColumnName(colnames[i]);
			sb.append("\tpublic void set" + StringUtil.firstCharToUpperCase(column) + "(" + sqlType2JavaType(colTypes[i]) + " " + 
					column + "){\r\n");
			if("String".equals(sqlType2JavaType(colTypes[i]))){
				sb.append("\t\tthis." + column + "=" + column + "==null?null:"+column+".trim();\r\n");
			}else{
				sb.append("\t\tthis." + column + "=" + column + ";\r\n");	
			}
			sb.append("\t}\r\n");
			sb.append("\tpublic " + sqlType2JavaType(colTypes[i]) + " get" + StringUtil.firstCharToUpperCase(column) + "(){\r\n");
			sb.append("\t\treturn " + column + ";\r\n");
			sb.append("\t}\r\n");
		}
	}
	/**
	 * 功能：生成所有属性
	 * @param sb
	 */
	private void processAllAttrs(StringBuffer sb,String[] colnames,String[] colTypes) {
		for (int i = 0; i < colnames.length; i++) {
			String type=sqlType2JavaType(colTypes[i]);
			sb.append("\tprivate " + type + " " + getColumnName(colnames[i]) + ";\r\n");
		}
	}
	/**
	 * 功能：获得列的数据类型
	 * @param sqlType
	 * @return
	 */
	private String sqlType2JavaType(String sqlType) {
		
		if(sqlType.equalsIgnoreCase("bit")){
			return "Boolean";
		}else if(sqlType.equalsIgnoreCase("tinyint")){
			return "Byte";
		}else if(sqlType.equalsIgnoreCase("smallint")){
			return "Short";
		}else if(sqlType.equalsIgnoreCase("int")){
			return "Long";
		}else if(sqlType.equalsIgnoreCase("bigint")){
			return "Long";
		}else if(sqlType.equalsIgnoreCase("float")){
			return "Float";
		}else if(sqlType.equalsIgnoreCase("decimal") || sqlType.equalsIgnoreCase("numeric") 
				|| sqlType.equalsIgnoreCase("real") || sqlType.equalsIgnoreCase("money") 
				|| sqlType.equalsIgnoreCase("smallmoney")){
			return "Double";
		}else if(sqlType.equalsIgnoreCase("varchar") || sqlType.equalsIgnoreCase("char") 
				|| sqlType.equalsIgnoreCase("nvarchar") || sqlType.equalsIgnoreCase("nchar") 
				|| sqlType.equalsIgnoreCase("text")){
			return "String";
		}else if(sqlType.equalsIgnoreCase("datetime")||sqlType.equalsIgnoreCase("timestamp")){
			return "java.util.Date";
		}else if(sqlType.equalsIgnoreCase("image")){
			return "java.sql.Blod";
		}
		
		return null;
	}
	public GenEntityUtil setRemovedTableNamePrefixes(String ...removedTableNamePrefixes) {
		this.removedTableNamePrefixes = removedTableNamePrefixes;
		return this;
	}

	public GenEntityUtil setBaseModelPackageName(String baseModelPackageName) {
		this.baseModelPackageName = baseModelPackageName;
		this.baseDaoPackageName=baseModelPackageName.replaceAll("entity", "dao");
		return this;
	}
	
	public GenEntityUtil setRemovedTableName(String ...removedTableName) {
		this.removedTableName = removedTableName;
		return this;
	}
}
